<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="UTF-8" />
        <!--  限制页面只能1.0倍，并设置 user-scalable=no，不允许用户手动缩放。-->
        <meta
            name="viewport"
            content="width=device-width, initial-scale=1.0 , minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
        />
        <!-- 强制Chromium内核，作用于360浏览器、QQ浏览器等国产双核浏览器 -->
        <meta name="renderer" content="webkit" />
        <!-- 强制Chromium内核，作用于其他双核浏览器 -->
        <meta name="force-rendering" content="webkit" />
        <!-- 如果有安装 Google Chrome Frame 插件则强制为Chromium内核，否则强制本机支持的最高版本IE内核，作用于IE浏览器 -->
        <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
        <!--    <meta name="referrer" content="strict-origin-when-cross-origin">-->
        <title></title>
        <!-- <link rel="stylesheet" href="lib/cesium/cesium-1.115/Widgets/widgets.css" type="text/css"> -->
        <link
            rel="stylesheet"
            href="./node_modules/cesium/Build/Cesium/Widgets/widgets.css"
            type="text/css"
        />
        <!-- <script src="lib/cesium/cesium-1.115/Cesium.js"></script> -->
        <script src="./node_modules/cesium//Build/Cesium/Cesium.js"></script>
        <!-- <link href="https://cesium.com/downloads/cesiumjs/releases/1.115/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
     <script src="https://cesium.com/downloads/cesiumjs/releases/1.115/Build/Cesium/Cesium.js"></script>-->
        <!--此版本可直接静态文件运行，高版本不行-->
        <!--<link href="https://cesium.com/downloads/cesiumjs/releases/1.105/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
    <script src="https://cesium.com/downloads/cesiumjs/releases/1.105/Build/Cesium/Cesium.js"></script>-->
        <style>
            body,
            html {
                margin: 0;
                padding: 0;
                background-color: #c1aef6;
            }

            /* 滚动条宽度 */
            ::-webkit-scrollbar {
                width: 4px;
                height: 4px;
                background-color: transparent;
            }

            /* 滚动条颜色 */
            ::-webkit-scrollbar-thumb {
                background-color: #5a80ef;
            }

            button {
                cursor: pointer;
            }

            .map {
                width: 100%;
                height: 100vh;

                #cesiumContainer {
                    position: absolute;
                    width: 100%;
                    height: 100%;
                }

                .content {
                    position: absolute;
                    width: 100%;
                    height: 100%;
                    pointer-events: none; /*事件穿透*/

                    & > div {
                        pointer-events: auto; /*静止穿透*/
                    }

                    fieldset {
                        display: flex;
                        flex-direction: column;
                        justify-items: center;

                        label {
                            display: flex;
                            line-height: 19px;
                            margin-top: 5px;
                            width: fit-content;
                            cursor: pointer;
                        }

                        button {
                            width: 90px;
                            margin: 5px auto 0 auto;
                        }
                    }

                    .model {
                        position: absolute;
                        top: 2%;
                        left: 2%;
                        background: rgba(88, 171, 239, 0.8);
                        padding: 10px;
                        max-height: 90%;
                        overflow: auto;
                        color: #ffffff;

                        .model-list {
                            table {
                                max-width: 350px;
                                border-spacing: 0;
                                border-collapse: collapse;
                                /*background-color: rgba(0, 0, 0, 0.5);*/

                                button {
                                    width: auto;
                                }

                                caption {
                                    font-weight: bold;
                                    font-size: 14px;
                                    line-height: 26px;
                                }

                                th,
                                td {
                                    text-align: center;
                                    /*border: 1px solid #0000ff;*/
                                    overflow: auto;
                                    font-size: 12px;
                                }

                                th {
                                    height: 30px;
                                }

                                td {
                                    height: 50px;
                                    padding: 2px;
                                    border: 2px #76cbf6 solid;
                                }

                                thead {
                                    color: white;
                                    background-color: #76cbf6;
                                }

                                tbody {
                                    display: block;
                                    width: calc(
                                        100%
                                    ); /*这里的8px是滚动条的宽度*/
                                    max-height: 125px;
                                    overflow-y: auto;
                                    -webkit-overflow-scrolling: touch;
                                    /*color: #212121;*/
                                }

                                tfoot {
                                    background-color: #71ea71;
                                }

                                thead tr,
                                tbody tr,
                                tfoot tr {
                                    box-sizing: border-box;
                                    table-layout: fixed;
                                    display: table;
                                    width: 100%;
                                    transition: background-color 0.3s ease;
                                }

                                tbody tr:hover {
                                    background-color: rgba(0, 0, 0, 0.6);
                                }

                                tbody tr:nth-of-type(odd) {
                                    /*background: #EEE;*/
                                }

                                tbody tr:nth-of-type(even) {
                                    /*background: #FFF;*/
                                }

                                tbody tr td {
                                    border-bottom: none;
                                }

                                tbody tr:last-child {
                                    td {
                                        border: 2px #76cbf6 solid;
                                    }
                                }
                            }
                        }

                        .model-add,
                        .model-adjust {
                        }

                        .model-adjust-info {
                            max-height: 500px;
                            overflow: auto;

                            .basic-info {
                                display: flex;
                                flex-direction: column;
                                max-height: 100px;
                                overflow: auto;

                                span:last-child {
                                    /*display: inline-block;*/
                                    max-width: 200px; /* 或者其他宽度 */
                                    white-space: normal;
                                    overflow-wrap: break-word; /* 替代旧版的 word-wrap */
                                    word-break: break-word; /* 根据需要可选，提供额外的换行控制 */
                                }
                            }
                        }
                    }

                    .mapEnv {
                        position: absolute;
                        top: 2%;
                        right: 2%;
                        background: rgba(88, 171, 239, 0.8);
                        padding: 10px;
                        max-height: 90%;
                        overflow: auto;
                        color: #ffffff;
                        /*width: 350px;*/

                        label {
                            /*  border: 1px red solid;*/

                            span:last-child {
                                width: 50px;
                            }
                        }
                    }
                }
            }
        </style>
    </head>

    <body>
        <div class="map">
            <div id="cesiumContainer"></div>
            <div class="content">
                <div class="model">
                    <!--模型服务添加-->
                    <div class="model-add">
                        <fieldset>
                            <legend style="margin: 0 auto">模型调整</legend>
                            <label for="name">
                                <span>名称：</span>
                                <input
                                    type="text"
                                    id="name"
                                    placeholder="名称"
                                />
                            </label>
                            <label for="serviceUrl">
                                <span>服务地址：</span>
                                <textarea
                                    rows="3"
                                    cols="30"
                                    id="serviceUrl"
                                    placeholder="服务地址"
                                ></textarea>
                            </label>
                            <button class="add">添加模型</button>
                        </fieldset>
                    </div>
                    <!--模型加载列表-->
                    <div class="model-list">
                        <fieldset>
                            <legend style="margin: 0 auto">
                                3dtiles加载列表
                            </legend>
                            <table
                                class="model-t"
                                cellpadding="0"
                                cellspacing="0"
                            >
                                <!--<caption>3dtiles加载列表</caption>-->
                                <thead>
                                    <tr>
                                        <th>序号</th>
                                        <th>名称</th>
                                        <th>服务地址</th>
                                        <th>操作</th>
                                    </tr>
                                </thead>
                                <tbody class="model-tb">
                                    <!-- <tr>
                             <td></td>
                             <td></td>
                             <td></td>
                             <td>
                                 <button class="adjust" value="99">调整</button>
                                 <button class="del" value="99">删除</button>
                             </td>
                         </tr>-->
                                </tbody>
                            </table>
                        </fieldset>
                    </div>
                    <!--模型位置调整-->
                    <div class="model-adjust" style="display: none">
                        <fieldset class="model-adjust-info">
                            <legend style="margin: 0 auto">模型信息</legend>
                            <div class="basic-info">
                                <label>
                                    <span>序号：</span>
                                    <span id="adjust-id"></span>
                                </label>
                                <label>
                                    <span>名称：</span>
                                    <span id="adjust-name"></span>
                                </label>
                                <label>
                                    <span>服务地址：</span>
                                    <span id="adjust-serviceUrl"></span>
                                </label>
                            </div>
                            <fieldset style="margin-top: 5px">
                                <legend>模型位置</legend>
                                <label for="lng">
                                    <span>经度：</span>
                                    <input
                                        type="number"
                                        id="lng"
                                        step="0.000005"
                                        placeholder="经度"
                                        data-bind="value: lng, valueUpdate: 'input'"
                                    />
                                </label>
                                <label for="lat">
                                    <span>纬度：</span>
                                    <input
                                        type="number"
                                        id="lat"
                                        step="0.000005"
                                        placeholder="纬度"
                                        data-bind="value: lat, valueUpdate: 'input'"
                                    />
                                </label>
                                <label for="alt">
                                    <span>高度：</span>
                                    <input
                                        type="number"
                                        id="alt"
                                        step="0.1"
                                        placeholder="高度"
                                        data-bind="value: alt, valueUpdate: 'input'"
                                    />
                                </label>
                                <button class="flyTo">定位至模型</button>
                            </fieldset>
                            <fieldset>
                                <legend>模型方向</legend>
                                <label for="x">
                                    <span>绕X轴旋转：</span>
                                    <input
                                        type="number"
                                        id="x"
                                        step="1.0"
                                        placeholder="X轴旋转角度"
                                        data-bind="value: x, valueUpdate: 'input'"
                                    />
                                </label>
                                <label for="y">
                                    <span>绕Y轴旋转：</span>
                                    <input
                                        type="number"
                                        id="y"
                                        step="1.0"
                                        placeholder="Y轴旋转角度"
                                        data-bind="value: y, valueUpdate: 'input'"
                                    />
                                </label>
                                <label for="z">
                                    <span>绕Z轴旋转：</span>
                                    <input
                                        type="number"
                                        id="z"
                                        step="1.0"
                                        placeholder="Z轴旋转角度"
                                        data-bind="value: z, valueUpdate: 'input'"
                                    />
                                </label>
                            </fieldset>
                            <fieldset>
                                <legend>其它参数</legend>
                                <label for="scale">
                                    <span>模型比例：</span>
                                    <input
                                        type="number"
                                        id="scale"
                                        step="0.01"
                                        placeholder="比例"
                                        data-bind="value: scale, valueUpdate: 'input'"
                                    />
                                </label>
                            </fieldset>
                            <button class="printDownload" style="width: 100px">
                                打印下载参数
                            </button>
                        </fieldset>
                    </div>
                </div>
                <div class="mapEnv">
                    <!--底图加载-->
                    <div class="imageLayer">
                        <fieldset>
                            <legend style="margin: 0 auto">底图加载</legend>
                            <label for="tdtYXANDYXZJ"
                                ><input
                                    type="radio"
                                    id="tdtYXANDYXZJ"
                                    name="layer"
                                    value="1"
                                    data-bind="checked: layerValue"
                                />天地图影像及注记
                            </label>
                            <label for="tdtSLANDSLZJ"
                                ><input
                                    type="radio"
                                    id="tdtSLANDSLZJ"
                                    name="layer"
                                    value="2"
                                    data-bind="checked: layerValue"
                                />天地图矢量及注记</label
                            >
                            <label for="bingYX"
                                ><input
                                    type="radio"
                                    id="bingYX"
                                    name="layer"
                                    value="3"
                                    data-bind="checked: layerValue"
                                />bing影像</label
                            >
                            <label for="arcgisYX"
                                ><input
                                    type="radio"
                                    id="arcgisYX"
                                    name="layer"
                                    value="4"
                                    data-bind="checked: layerValue"
                                />arcgis影像</label
                            >
                            <label for="JAQLHB"
                                ><input
                                    type="radio"
                                    id="JAQLHB"
                                    name="layer"
                                    value="5"
                                    data-bind="checked: layerValue"
                                />金安区蓝黑版</label
                            >
                            <label for="layerNone"
                                ><input
                                    type="radio"
                                    id="layerNone"
                                    name="layer"
                                    value="-1"
                                    data-bind="checked: layerValue"
                                />无</label
                            >
                        </fieldset>
                    </div>
                    <!--地形加载-->
                    <div class="terrain">
                        <fieldset>
                            <legend style="margin: 0 auto">地形加载</legend>
                            <label for="bingTerrain"
                                ><input
                                    type="radio"
                                    id="bingTerrain"
                                    name="terrain"
                                    value="1"
                                    data-bind="checked: terrainValue"
                                />bing地形
                            </label>
                            <label for="arcgisTerrain"
                                ><input
                                    type="radio"
                                    id="arcgisTerrain"
                                    name="terrain"
                                    value="2"
                                    data-bind="checked: terrainValue"
                                />arcgis地形
                            </label>
                            <label for="terrainNone"
                                ><input
                                    type="radio"
                                    id="terrainNone"
                                    name="terrain"
                                    value="-1"
                                    data-bind="checked: terrainValue"
                                />无</label
                            >
                        </fieldset>
                    </div>
                    <!--场景调整-->
                    <div class="mapScene">
                        <fieldset>
                            <legend style="margin: 0 auto">场景调整</legend>
                            <label for="depthTestAgainstTerrain"
                                ><input
                                    type="checkbox"
                                    id="depthTestAgainstTerrain"
                                    data-bind="checked: depthTestAgainstTerrain"
                                />深度检测</label
                            >
                            <label for="wireframeTerrain"
                                ><input
                                    type="checkbox"
                                    id="wireframeTerrain"
                                    data-bind="checked: wireframeTerrain"
                                />球面三角网</label
                            >
                            <label for="mapTime">
                                <span>场景时间：</span>
                                <input
                                    id="mapTime"
                                    type="range"
                                    min="0"
                                    max="1439"
                                    step="10"
                                    value="0"
                                    data-bind="value: mapTime, valueUpdate: 'input'"
                                />
                                <span class="mapTimeVal"></span>
                            </label>
                            <label for="brightness">
                                <span>场景亮度：</span>
                                <input
                                    id="brightness"
                                    type="range"
                                    min="0.0"
                                    max="2.0"
                                    step="0.1"
                                    value="1.0"
                                    data-bind="value: brightness, valueUpdate: 'input'"
                                />
                                <span data-bind="html: brightness"></span>
                            </label>
                            <fieldset style="margin-top: 5px">
                                <legend>泛光调整</legend>
                                <label for="floodlightEnabled"
                                    ><input
                                        type="checkbox"
                                        id="floodlightEnabled"
                                        data-bind="checked: floodlightEnabled"
                                    />泛光开启</label
                                >
                                <label for="floodlightGlowOnly"
                                    ><input
                                        type="checkbox"
                                        id="floodlightGlowOnly"
                                        data-bind="checked: floodlightGlowOnly"
                                    />只保留泛光</label
                                >
                                <label for="floodlightContrast">
                                    <span>对比度：</span>
                                    <input
                                        id="floodlightContrast"
                                        type="range"
                                        min="-255.0"
                                        max="255.0"
                                        step="0.01"
                                        data-bind="value: floodlightContrast, valueUpdate: 'input'"
                                    />
                                    <span
                                        data-bind="html: floodlightContrast"
                                    ></span>
                                </label>
                                <label for="floodlightBrightness">
                                    <span>亮度：</span>
                                    <input
                                        id="floodlightBrightness"
                                        type="range"
                                        min="-1.0"
                                        max="1.0"
                                        step="0.01"
                                        data-bind="value: floodlightBrightness, valueUpdate: 'input'"
                                    />
                                    <span
                                        data-bind="html: floodlightBrightness"
                                    ></span>
                                </label>
                                <label for="floodlightDelta">
                                    <span>阈值(delta)：</span>
                                    <input
                                        id="floodlightDelta"
                                        type="range"
                                        min="1"
                                        max="5"
                                        step="0.01"
                                        data-bind="value: floodlightDelta, valueUpdate: 'input'"
                                    />
                                    <span
                                        data-bind="html: floodlightDelta"
                                    ></span>
                                </label>
                                <label for="floodlightSigma">
                                    <span>高斯模糊(sigma)：</span>
                                    <input
                                        id="floodlightSigma"
                                        type="range"
                                        min="1"
                                        max="10"
                                        step="0.01"
                                        data-bind="value: floodlightSigma, valueUpdate: 'input'"
                                    />
                                    <span
                                        data-bind="html: floodlightSigma"
                                    ></span>
                                </label>
                                <label for="floodlightStepSize">
                                    <span>步长(stepSize)：</span>
                                    <input
                                        id="floodlightStepSize"
                                        type="range"
                                        min="0"
                                        max="7"
                                        step="0.01"
                                        data-bind="value: floodlightStepSize, valueUpdate: 'input'"
                                    />
                                    <span
                                        data-bind="html: floodlightStepSize"
                                    ></span>
                                </label>
                            </fieldset>
                        </fieldset>
                    </div>
                </div>
            </div>
        </div>
        <script>
            //
            let mask // 遮罩dom
            let maskCount = 0 // 遮罩计数

            // 创建遮罩
            function createMask() {
                maskCount++ // 遮罩计数+1
                if (mask) return // 遮罩存在不创建
                // 创建遮罩层
                mask = document.createElement('div')
                mask.style.position = 'fixed'
                mask.style.top = 0
                mask.style.left = 0
                mask.style.right = 0
                mask.style.bottom = 0
                mask.style.background = 'rgba(0, 0, 0, 0.5)'
                mask.style.zIndex = 9999 // 确保遮罩层在其他内容之上
                mask.innerHTML = `<div style="position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);">
                            <div style="font-size: 20px;color: #fff;font-weight: bold;">加载中...</div>
                        </div>`
                // 将遮罩层添加到文档中
                document.body.appendChild(mask)
            }

            // 删除遮罩
            function removeMask() {
                maskCount && maskCount-- // 遮罩计数-1
                // 多个遮罩时同时存在时，等待最后一个遮罩，才给删除
                if (mask && maskCount === 0) {
                    // 移除遮罩层
                    document.body.removeChild(mask)
                    mask = null
                }
            }

            let viewer // 地图视图对象

            // 创建场景
            function initViewer(opt = {}) {
                // cesium官网申请key-->https://www.cesium.com/
                Cesium.Ion.defaultAccessToken =
                    'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2YmI1YmMyMC0zMmI3LTQzODYtYWI2Yi0zNTQwNzczYzI2NzUiLCJpZCI6NjMzMjYsImlhdCI6MTY0NjcwMzA3MH0.oKagb5s-dQb-pzTin3KCSjutqq-unFIj6GSdcF_Y5Lc'
                //
                viewer = new Cesium.Viewer(opt.target ?? 'cesiumContainer', {
                    contextOptions: {
                        webgl: {
                            // alpha: true, // 透明度
                            preserveDrawingBuffer: true, //设置canvas截图使用，不设置截屏图片黑色
                        },
                    }, // 传递给 Scene 的上下文和 WebGL 创建属性
                    // msaaSamples: 8, // 抗锯齿 1.91^ // 开高后-手机浏览器会不显示
                    animation: true, // 动画部件
                    timeline: true, // 时间轴部件
                    // shouldAnimate: true, // 太阳模拟时钟时间,时间控制函数
                    // clockViewModel: new Cesium.ClockViewModel(clock),  // 当shouldAnimate为ture,执行当前设置的时间区间动画
                    baseLayerPicker: false, // 基础图层部件
                    fullscreenButton: false, // 全屏按钮部件
                    vrButton: false, // vr部件
                    geocoder: false, // 地名查找位置搜索部件
                    homeButton: false, // home按钮
                    infoBox: false, // 消息框部件-点击要素之后显示的信息
                    sceneModePicker: false, // 二三维切换部件
                    selectionIndicator: false, // “选择指示器”构件
                    navigationHelpButton: false, // 导航帮助按钮
                    navigationInstructionsInitiallyVisible: false, // 导航说明显示
                    scene3DOnly: true, // 每个几何图形实例将仅以3D形式呈现，以节省GPU内存。
                    // shadows: true, // 确定阴影是否由光源投射。
                    // terrainShadows: Cesium.ShadowMode.DISABLED, // 不接收光照和阴影
                    // terrainShadows: Cesium.ShadowMode.ENABLED, // 接收光照和阴影
                    // selectedImageryProviderViewModel:{}, // 当前基础--影像图层的视图模型（如果未提供，则使用第一个可用的基础图层）仅当“baseLayerPicker”设置为 true 时，此值才有效。
                    // imageryProviderViewModels: [],  //可以从BaseLayerPicker中选择的ProviderViewModels数组。仅当“ baseLayerPicker”设置为true时，此值才有效。
                    // selectedTerrainProviderViewModel: {}, // 当前基础--地形图层的视图模型（如果未提供）将使用第一个可用的基础图层。仅当“ baseLayerPicker”设置为true时，此值才有效。
                    // terrainProviderViewModels: [],   // 可以从BaseLayerPicker中选择的ProviderViewModels数组。仅当“ baseLayerPicker”设置为true时，此值才有效。
                    // imageryProvider: new Cesium.SingleTileImageryProvider({url: img3}), // 加载不同的地图服务。仅当“ baseLayerPicker”设置为false时，此值才有效。
                    // baseLayer:new Cesium.ImageryLayer(imageryProvider,options), // 应用于地球的最底部影像图层。如果设置为 ，则不会添加任何影像提供程序。仅当“baseLayerPicker”设置为 false 时，此值才有效。false
                    // terrain: new Cesium.Terrain(Cesium.CesiumTerrainProvider.fromUrl("https://myTestTerrain.com")),//处理异步地形提供程序的地形对象。只能指定 options.terrainProvider 是否未定义。
                    // orderIndependentTranslucency: true, // 如果为true且配置支持，则使用顺序无关的透明性。 // 去掉大气黑圈
                    /*baseLayer: new Cesium.ImageryLayer.fromProviderAsync(
                Cesium.TileMapServiceImageryProvider.fromUrl(
                    // `${process.env.BASE_URL}/lib/cesium/Cesium-1.109/Assets/Textures/NaturalEarthII`
                    `cesium/Cesium-1.115/Assets/Textures/NaturalEarthII`
                )
            ),*/
                    terrainProvider: new Cesium.EllipsoidTerrainProvider(), // 地形服务设置,无地形
                    // 无影像
                    imageryProvider: new Cesium.SingleTileImageryProvider({
                        url: '',
                    }),
                    // depthPlaneEllipsoidOffset: 0.0
                })
                viewer.imageryLayers.remove(viewer.imageryLayers.get(0)) // 删除默认地图服务
                viewer._cesiumWidget._creditContainer.style.display = 'none' // 隐藏版权
                viewer.animation.container.style.display = 'none' // 隐藏掉时钟
                viewer.timeline.container.style.display = 'none' // 隐藏时间轴
                viewer.scene.debugShowFramesPerSecond = false // 开启场景FPS显示
                viewer.scene.globe.depthTestAgainstTerrain = true // 高程遮挡效果
                // viewer.scene.globe.show = true; // 是否显示地球
                // viewer.scene.globe.translucency.enabled = true; // 地球是否半透明

                viewer.scene.globe.baseColor =
                    Cesium.Color.fromCssColorString('rgb(54,72,92)') // 地球颜色
                // 当相机在地下或地球仪半透明时渲染地球背面的颜色， 根据相机的距离与地球颜色混合。
                // viewer.scene.globe.undergroundColor = Cesium.Color.fromCssColorString('rgba(8,238,181,0.1)'); // 要禁用地下着色，请设置为 。undergroundColor = undefined
                viewer.scene.sun.show = false // 太阳
                viewer.scene.moon.show = false // 月亮
                // viewer.scene.fog.enable = false; // 雾
                // viewer.scene.fog.density = 0.0005; // 设置雾效
                // viewer.scene.fog.minimumBrightness = 0.5;
                // 星空背景
                // viewer.scene.skyBox = new Cesium.SkyBox({
                //   sources: {
                //     positiveX: nx,
                //     negativeX: nx,
                //     positiveY: nx,
                //     negativeY: nx,
                //     positiveZ: nx,
                //     negativeZ: nx
                //   }
                // });
                // viewer.scene.skyBox = undefined; // 不显示星空
                // viewer.scene.skyAtmosphere.show = false; // 大气
                // viewer.scene.backgroundColor = Cesium.Color.fromCssColorString('rgba(0,0,0,0)'); // 星空盒子背景颜色

                // 去掉entity的点击事件 start
                viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
                    Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
                )
                viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
                    Cesium.ScreenSpaceEventType.LEFT_CLICK
                )
                // 去掉entity的点击事件 end
                // 设置相机位置
                viewer.camera.setView({
                    // 设置相机位置
                    destination: Cesium.Cartesian3.fromDegrees(
                        108.885436,
                        30.054604,
                        17036414
                    ),
                    orientation: {
                        // 初始视角
                        heading: Cesium.Math.toRadians(0),
                        pitch: Cesium.Math.toRadians(-90),
                        roll: Cesium.Math.toRadians(0),
                    },
                })
                return viewer
            }

            // 设置场景时间为北京时间
            function setTime() {
                // 设置时间为北京时间
                viewer.animation.viewModel.timeFormatter = CesiumTimeFormatter
                viewer.timeline.makeLabel = CesiumDateTimeFormatter
                viewer.animation.viewModel.dateFormatter = CesiumDateFormatter

                // cesium时钟时间格式化函数
                function CesiumTimeFormatter(datetime) {
                    const julianDT = new Cesium.JulianDate()
                    Cesium.JulianDate.addHours(datetime, 8, julianDT)
                    const gregorianDT =
                        Cesium.JulianDate.toGregorianDate(julianDT)
                    let hour = gregorianDT.hour + ''
                    let minute = gregorianDT.minute + ''
                    let second = gregorianDT.second + ''
                    return `${hour.padStart(2, '0')}:${minute.padStart(
                        2,
                        '0'
                    )}:${second.padStart(2, '0')}`
                }

                // cesium时钟日期格式化函数
                function CesiumDateFormatter(datetime) {
                    const julianDT = new Cesium.JulianDate()
                    Cesium.JulianDate.addHours(datetime, 8, julianDT)
                    const gregorianDT =
                        Cesium.JulianDate.toGregorianDate(julianDT)
                    const month = gregorianDT.month + ''
                    const day = gregorianDT.day + ''
                    return `${gregorianDT.year}年${month.padStart(
                        2,
                        '0'
                    )}月${day.padStart(2, '0')}日`
                }

                // cesium时间轴格式化函数
                function CesiumDateTimeFormatter(datetime) {
                    const julianDT = new Cesium.JulianDate()
                    Cesium.JulianDate.addHours(datetime, 8, julianDT)
                    const gregorianDT =
                        Cesium.JulianDate.toGregorianDate(julianDT)
                    const year = gregorianDT.year + ''
                    const month = gregorianDT.month + ''
                    const day = gregorianDT.day + ''
                    const hour = gregorianDT.hour + ''
                    const minute = gregorianDT.minute + ''
                    const seconds = gregorianDT.second + ''
                    return `${year}年${month.padStart(2, '0')}月${day.padStart(
                        2,
                        '0'
                    )}日 ${hour.padStart(2, '0')}:${minute.padStart(
                        2,
                        '0'
                    )}:${seconds.padStart(2, '0')}`
                }

                /*// 设定起始时间
        const start = Cesium.JulianDate.fromDate(new Date('2022/12/25 10:00:00'));
        // 设定终止时间
        const end = Cesium.JulianDate.fromDate(new Date('2022/12/25 14:00:00'));
        // 时间线范围
        viewer.timeline.zoomTo(start, end);
        // 定义clock事件
        const clock = viewer.clock;
        // 设定clock的起始时间
        clock.startTime = start;
        // 设定clock的终止时间
        clock.stopTime = end;
        // 设定clock的当前时间
        clock.currentTime = Cesium.JulianDate.fromDate(new Date('2022/12/25 10:00:00'));
        // 设定clock范围为不断循环
        clock.clockRange = Cesium.ClockRange.LOOP_STOP;
        // 设定时间速率
        clock.multiplier = 1;
        // 启用自动时间，让时钟自动前进
        clock.shouldAnimate = true;
        */
            }

            // 修改模型矩阵信息
            function update3dTilesMatrix(opt = {}) {
                const { tileSet, lng, lat, alt, x, y, z, scale } = opt
                const modelMatrix = tileSet.root.transform
                // 获取模型默认位置
                const position = Cesium.Matrix4.getTranslation(
                    modelMatrix,
                    new Cesium.Cartesian3()
                )
                const cartographic = Cesium.Cartographic.fromCartesian(position)
                const longitude = Cesium.Math.toDegrees(cartographic.longitude)
                const latitude = Cesium.Math.toDegrees(cartographic.latitude)
                const altitude = cartographic.height
                const _lng = lng ?? Number(longitude.toFixed(6)) // 经度
                const _lat = lat ?? Number(latitude.toFixed(6)) // 纬度
                const _alt = alt ?? Number(altitude.toFixed(4)) // 高度
                // 位置变换
                const _position = Cesium.Cartesian3.fromDegrees(
                    _lng,
                    _lat,
                    _alt
                )
                // 变换后矩阵
                const m = Cesium.Transforms.eastNorthUpToFixedFrame(_position)
                // 旋转x轴
                if (x || x === 0) {
                    const mx = Cesium.Matrix3.fromRotationX(
                        Cesium.Math.toRadians(x)
                    )
                    const rotate = Cesium.Matrix4.fromRotationTranslation(mx)
                    Cesium.Matrix4.multiply(m, rotate, m)
                }
                // 旋转y轴
                if (y || y === 0) {
                    const my = Cesium.Matrix3.fromRotationY(
                        Cesium.Math.toRadians(y)
                    )
                    const rotate = Cesium.Matrix4.fromRotationTranslation(my)
                    Cesium.Matrix4.multiply(m, rotate, m)
                }
                // 旋转z轴
                if (z || z === 0) {
                    const mz = Cesium.Matrix3.fromRotationZ(
                        Cesium.Math.toRadians(z)
                    )
                    const rotate = Cesium.Matrix4.fromRotationTranslation(mz)
                    Cesium.Matrix4.multiply(m, rotate, m)
                }
                // 缩放
                if (scale || scale === 0) {
                    const _scale = Cesium.Matrix4.fromUniformScale(scale)
                    Cesium.Matrix4.multiply(m, _scale, m)
                }
                // 修改自定义customAttr中存储的位置信息，用于后面反显
                tileSet.customAttr.position = {
                    lng: _lng,
                    lat: _lat,
                    alt: _alt,
                }
                tileSet.customAttr.rotation = {
                    x: x ?? 0.0,
                    y: y ?? 0.0,
                    z: z ?? 0.0,
                }
                tileSet.customAttr.scale = scale ?? 1.0
                return m
            }

            // 添加模型
            async function add3dTileSet(opt = {}) {
                const url = opt.url // 模型地址
                if (!url) return
                const position = opt.position // 模型位置
                const rotation = opt.rotation // 自定义旋转方向（旋转模型）
                const scale = opt.scale // 模型参数配置
                // const customId = opt.customId; // 自定义id
                const tileSetOpt = opt.options || {} // 模型参数配置
                let tileSet // 模型对象
                try {
                    // 模型参数配置
                    const options = {
                        // show: true, // 显示隐藏
                        // shadows: Cesium.ShadowMode.DISABLED, // 不接收光照和阴影
                        // shadows: Cesium.ShadowMode.ENABLED, // 对象投射并接收阴影。
                        maximumMemoryUsage: 1024 * 2, // tileset 可以使用的最大内存量
                        // skipLevelOfDetail: false, // 开启细节跳过功能
                        // maximumScreenSpaceError: 16, // 最大屏幕误差，默认16，数值加大，能让最终成像变模糊
                        // skipScreenSpaceErrorFactor: 16, // 最小屏幕误差因子，可以划定加载的瓦片数，默认16
                        // baseScreenSpaceError: 1024,  // 屏幕像素细节，默认1024
                        // skipLevels: 0, // 跳过加载图层数，默认为1
                        // immediatelyLoadDesiredLevelOfDetail: false, // 只有满足最大屏幕空间错误的磁贴才会被下载。跳过因子将被忽略，仅加载所需的切片
                        // loadSiblings: true, // 是否批量加载模型切片(自动加载切片的兄弟节点)
                        // backFaceCulling: true, // 背面剔除，适用于glTF
                        // enableShowOutline: false,  // 是否启用模型加载的扩展功能
                        // cullRequestsWhileMovingMultiplier: 60, // 默认60，数值越大剔除的面数越多
                        // cullWithChildrenBounds: true, // 剔除子瓦片
                        // preloadWhenHidden: true // 预加载瓷砖，但不显示
                        // debugShowBoundingVolume: true // 则呈现每个磁贴的边界体积。
                    }
                    tileSet = await Cesium.Cesium3DTileset.fromUrl(
                        url,
                        Object.assign(options, tileSetOpt)
                    )
                    // 添加到primitives
                    viewer.scene.primitives.add(tileSet)
                    // 给模型赋值自己定义数据
                    tileSet.customAttr = opt
                    // 修改模型位置
                    tileSet._root.transform = update3dTilesMatrix({
                        tileSet,
                        ...position,
                        ...rotation,
                        scale,
                    })
                    // 飞行到模型
                    opt.autoPan && viewer.flyTo(tileSet, { duration: 0.0 })
                } catch (e) {
                    console.error(`Error creating tileSet: ${e}`)
                }
                /*// 测试延迟
        await new Promise((resolve) => {
            setTimeout(() => resolve(), 2000);
        });*/
                return tileSet
            }

            // ---------------------------------------------------------
            // 获取dom
            const modelName = document.getElementById('name')
            const modelUrl = document.getElementById('serviceUrl')
            const addModel = document.querySelector('.model-add .add')
            const modelTb = document.querySelector('.model-tb')
            const adjust = document.querySelector('.model-adjust')
            const adjustId = document.getElementById('adjust-id')
            const adjustName = document.getElementById('adjust-name')
            const adjustServiceUrl =
                document.getElementById('adjust-serviceUrl')
            const modelFlyTo = document.querySelector('.model-adjust .flyTo')
            const modelPrintDownload = document.querySelector(
                '.model-adjust .printDownload'
            )
            const tileSetList = new Map() // 模型加载成功存储列表
            let modelId = 0 // 模型id,一直累加防止重复
            // 添加模型到表格中
            function add3DTileSetToTable(tileSet, name, url) {
                if (!tileSet) {
                    alert('模型加载失败')
                    return
                }
                // 存储
                modelId++ // 计数累加
                const id = modelId.toString()
                tileSetList.set(id, { id, name, url, tileSet })
                // 添加至表格
                const tr = document.createElement('tr')
                tr.innerHTML = `<td>${id}</td>
                <td>${name}</td>
                <td>${url}</td>
                <td>
                    <button class="adjust" value=${id}>调整</button>
                    <button class="del" value=${id}>删除</button>
                </td>`
                modelTb.appendChild(tr)
                // 清空输入框
                modelName.value = ''
                modelUrl.value = ''
            }

            // 监听--添加模型--点击事件
            addModel.addEventListener('click', async () => {
                const name = modelName.value
                const url = modelUrl.value
                // const url ='./tiles/tileset.json'  
                console.log('url: ', url);
                if (!url) {
                    console.error('模型加载失败')
                    alert('模型加载失败')
                    return
                }
                createMask() // 打开遮罩
                // 添加模型
                const tileSet = await add3dTileSet({
                    url,
                    options: {
                        shadows: Cesium.ShadowMode.DISABLED, // 不接收光照和阴影
                        // shadows: Cesium.ShadowMode.ENABLED, // 对象投射并接收阴影。
                    },
                    autoPan: true, // 自动定位
                    // position: {
                    //     lng: 116.53357, // 经度
                    //     lat: 31.752795, // 维度
                    //     alt: -70.0, // 高度
                    // },
                    // rotation: {
                    //     x: 0.0, // x方向旋转角度
                    //     y: 0.0, // y方向旋转角度
                    //     z: 0.0, // z方向旋转角度
                    // },
                    // scale: 1.0 // 模型缩放比例
                })
                add3DTileSetToTable(tileSet, name, url) // 添加模型到表格中
                removeMask() // 关闭遮罩
            })
            // -------------------------------------------------------------
            // 当前正在调整的模型--参数
            const transform = {
                lng: 0.0,
                lat: 0.0,
                alt: 0.0,
                x: 0.0,
                y: 0.0,
                z: 0.0,
                scale: 0.0,
            }
            let adjustTileSetId = null // 当前正在调整的模型-id
            // 监测transform中的属性，KnockoutJS轻量级的UI类库
            Cesium.knockout.track(transform)
            // 激活属性, 将transform对象与html控件绑定
            Cesium.knockout.applyBindings(transform, adjust)

            // 调整数据至空、隐藏面板
            function clearAdjust() {
                adjust.style.display = 'none'
                adjustTileSetId = null
                Object.keys(transform).forEach(key => (transform[key] = 0.0))
                adjustId.innerHTML = ''
                adjustName.innerHTML = ''
                adjustServiceUrl.innerHTML = ''
                modelTb
                    .querySelectorAll('tr')
                    .forEach(tr => (tr.style.backgroundColor = ''))
            }

            // 表格点击-删除模型信息
            function removeTileSet(e) {
                const id = e.target.value // 获取删除按钮
                const res = confirm(`确定删除序号为${id}的模型？`)
                if (!res) return
                const { tileSet } = tileSetList.get(id) || {}
                // console.log('--------------',id,tileSet,tileSetList)
                if (!tileSet) return
                viewer.scene.primitives.remove(tileSet) // 地图中移除
                tileSetList.delete(id) // 移除列表
                modelTb.removeChild(e.target.parentNode.parentNode) // 移除表格
                // 判断是否是当前正在调整的
                if (adjustTileSetId === id) clearAdjust()
            }

            // 表格点击-调整模型信息
            function adjustTileSetInfo(e) {
                // 清空上一次模型调整信息
                clearAdjust()
                // 显示模型参数dom信息
                adjust.style.display = 'block'
                // 表格选中样式
                e.target.parentNode.parentNode.style.backgroundColor =
                    'rgba(4,126,246,0.8)'
                // 获取模型实例
                const { tileSet, id, name, url } =
                    tileSetList.get(e.target.value) || {}
                /*const modelMatrix = tileSet.root.transform;
        const position = Cesium.Matrix4.getTranslation(modelMatrix, new Cesium.Cartesian3());
        const cartographic = Cesium.Cartographic.fromCartesian(position);
        // 提取经度和纬度，注意结果是以弧度表示的，如果需要度的话需要进行转换
        const longitude = Cesium.Math.toDegrees(cartographic.longitude);
        const latitude = Cesium.Math.toDegrees(cartographic.latitude);
        // altitude是高度，如果你的模型是在地球表面，这个值通常是相对于海平面的高度
        const altitude = cartographic.height;
        // 提取缩放比例
        const scale = Cesium.Matrix4.getScale(modelMatrix, new Cesium.Cartesian3());
        console.log('---------------',longitude,latitude,altitude,scale.x)*/
                // 获取自定义属性--也可自行逆向计算获取，目前尝试只能逆向获取position和scale
                const { position, rotation, scale } = tileSet.customAttr
                const { lng, lat, alt } = position
                const { x, y, z } = rotation
                // 赋值基础信息
                adjustId.innerHTML = id
                adjustName.innerHTML = name
                adjustServiceUrl.innerHTML = url
                // 赋值修改参数
                transform.lng = lng.toFixed(6)
                transform.lat = lat.toFixed(6)
                transform.alt = alt.toFixed(4)
                transform.x = x.toFixed(1)
                transform.y = y.toFixed(1)
                transform.z = z.toFixed(1)
                transform.scale = scale.toFixed(2)
                adjustTileSetId = id
                // 定位至模型
                viewer.flyTo(tileSet, { duration: 0.0 })
            }

            // 调整位置
            function adjustTileSetMatrix() {
                if (!adjustTileSetId) return
                const { tileSet } = tileSetList.get(adjustTileSetId) || {}
                // console.log('transform', transform); // Number('')等于0
                tileSet._root.transform = update3dTilesMatrix({
                    tileSet,
                    lng: Number(transform.lng),
                    lat: Number(transform.lat),
                    alt: Number(transform.alt),
                    x: Number(transform.x),
                    y: Number(transform.y),
                    z: Number(transform.z),
                    scale: Number(transform.scale),
                })
            }

            // 监听属性变化
            for (const name in transform) {
                if (transform.hasOwnProperty(name)) {
                    // 监听控件的变化事件
                    Cesium.knockout
                        .getObservable(transform, name)
                        .subscribe(adjustTileSetMatrix)
                }
            }
            // 监听--模型列表--点击事件
            modelTb.addEventListener('click', e => {
                // 调整--按钮
                e.target.className === 'adjust' && adjustTileSetInfo(e)
                // 删除--按钮
                e.target.className === 'del' && removeTileSet(e)
            })
            // 监听--飞行到模型--点击事件
            modelFlyTo.addEventListener('click', () => {
                if (!adjustTileSetId) return
                const { tileSet } = tileSetList.get(adjustTileSetId) || {}
                viewer.flyTo(tileSet, { duration: 0.0 })
            })

            /**
             * 下载Json工具
             * @param str {string} json字符串
             * @param fileName {string} 下载后文件名
             */
            function saveAsJson(str, fileName) {
                //指定类型文件类型application/json;charset=utf-8
                const blob = new Blob([str], {
                    type: 'application/json;charset=utf-8',
                })
                const href = URL.createObjectURL(blob)
                const alink = document.createElement('a')
                alink.style.display = 'none'
                alink.download = fileName // 下载后文件名
                alink.href = href
                document.body.appendChild(alink)
                alink.click()
                document.body.removeChild(alink) // 下载完成移除元素
                URL.revokeObjectURL(href) // 释放掉blob对象
            }

            // 监听--打印下载参数
            modelPrintDownload.addEventListener('click', () => {
                if (!adjustTileSetId) return
                const { id, name, url, tileSet } =
                    tileSetList.get(adjustTileSetId) || {}
                const attr = {
                    id,
                    name,
                    url,
                    position: tileSet.customAttr.position,
                    rotation: tileSet.customAttr.rotation,
                    scale: tileSet.customAttr.scale,
                }
                const attrJson = JSON.stringify(attr)
                console.log(`序号(${id})：`, attr)
                console.log(`序号(${id})：`, attrJson)
                saveAsJson(attrJson, `序号(${id})-3dtiles调整参数.json`)
            })
            // ---------------底图加载---------------------------------------
            // 存储底图图层对象
            const mapLayer = new Map()
            //
            const layerChecked = {
                layerValue: '-1',
            }
            // 监测属性，KnockoutJS轻量级的UI类库
            Cesium.knockout.track(layerChecked)
            // 激活属性, 与html控件绑定
            Cesium.knockout.applyBindings(
                layerChecked,
                document.querySelector('.imageLayer')
            )

            // 添加/删除底图
            async function setLayer(val) {
                createMask() // 打开遮罩
                const tdtKey = 'a8ab0f5135c76369a8bf9f09e5026946'
                // 清空集合中服务
                const delLayerAll = () => {
                    for (const [, value] of mapLayer) {
                        for (let i = value.length - 1; i >= 0; i--) {
                            viewer.imageryLayers.remove(value[i])
                            // value.splice(i, 1);
                        }
                    }
                    mapLayer.clear()
                }
                // 清除上一次选择的图层
                delLayerAll()
                //
                try {
                    switch (val) {
                        // 天地图影像及注记
                        case '1':
                            ;(() => {
                                // 影像--_w球面墨卡托投影
                                const layer1 =
                                    viewer.imageryLayers.addImageryProvider(
                                        new Cesium.WebMapTileServiceImageryProvider(
                                            {
                                                url: `http://{s}.tianditu.gov.cn/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${tdtKey}`,
                                                subdomains: [
                                                    't0',
                                                    't1',
                                                    't2',
                                                    't3',
                                                    't4',
                                                    't5',
                                                    't6',
                                                    't7',
                                                ],
                                                tilingScheme:
                                                    new Cesium.WebMercatorTilingScheme(),
                                                minimumLevel: 1, //最小层级
                                                maximumLevel: 18, //最大层级
                                            }
                                        )
                                    )
                                // 影像注记--_w球面墨卡托投影
                                const layer2 =
                                    viewer.imageryLayers.addImageryProvider(
                                        new Cesium.WebMapTileServiceImageryProvider(
                                            {
                                                url: `http://{s}.tianditu.gov.cn/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${tdtKey}`,
                                                subdomains: [
                                                    't0',
                                                    't1',
                                                    't2',
                                                    't3',
                                                    't4',
                                                    't5',
                                                    't6',
                                                    't7',
                                                ],
                                                tilingScheme:
                                                    new Cesium.WebMercatorTilingScheme(),
                                                minimumLevel: 1, //最小层级
                                                maximumLevel: 18, //最大层级
                                            }
                                        )
                                    )
                                // 存储
                                mapLayer.set(val, [layer1, layer2])
                            })()
                            break
                        // 天地图矢量及注记
                        case '2':
                            ;(() => {
                                // 矢量--_w球面墨卡托投影
                                const layer1 =
                                    viewer.imageryLayers.addImageryProvider(
                                        new Cesium.WebMapTileServiceImageryProvider(
                                            {
                                                url: `http://{s}.tianditu.gov.cn/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=vec&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${tdtKey}`,
                                                subdomains: [
                                                    't0',
                                                    't1',
                                                    't2',
                                                    't3',
                                                    't4',
                                                    't5',
                                                    't6',
                                                    't7',
                                                ],
                                                tilingScheme:
                                                    new Cesium.WebMercatorTilingScheme(),
                                                minimumLevel: 1, //最小层级
                                                maximumLevel: 18, //最大层级
                                            }
                                        )
                                    )
                                // 矢量注记--_w球面墨卡托投影
                                const layer2 =
                                    viewer.imageryLayers.addImageryProvider(
                                        new Cesium.WebMapTileServiceImageryProvider(
                                            {
                                                url: `http://{s}.tianditu.gov.cn/cva_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cva&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${tdtKey}`,
                                                subdomains: [
                                                    't0',
                                                    't1',
                                                    't2',
                                                    't3',
                                                    't4',
                                                    't5',
                                                    't6',
                                                    't7',
                                                ],
                                                tilingScheme:
                                                    new Cesium.WebMercatorTilingScheme(),
                                                minimumLevel: 1, //最小层级
                                                maximumLevel: 18, //最大层级
                                            }
                                        )
                                    )
                                // 存储
                                mapLayer.set(val, [layer1, layer2])
                            })()
                            break
                        // bing影像
                        case '3':
                            /*// bing影像--标准调用方法
                    await (async () => {
                        try {
                            const layerOpt = await Cesium.BingMapsImageryProvider.fromUrl("https://dev.virtualearth.net", {
                                // 申请key地址https://www.bingmapsportal.com/
                                key: "AlPjkvOGHQaR_9Rnh-wGgqN1jP0hJVwfn7ffsaQsX2DEgybb8So3sDoeDXkMS1Sr",
                                mapStyle: Cesium.BingMapsStyle.AERIAL//可选参数，指定地图样式
                            });
                            const layer = viewer.imageryLayers.addImageryProvider(layerOpt);
                            // 存储
                            mapLayer.set(val, [layer]);
                        } catch (e) {
                            console.error(e)
                        }
                    })()*/
                            // cesium官网仓库默认资源服务加载，cesium官网申请key-->https://www.cesium.com/，key仓库地址 https://ion.cesium.com/assets/
                            await (async () => {
                                try {
                                    const layerOpt =
                                        await Cesium.IonImageryProvider.fromAssetId(
                                            2
                                        )
                                    const layer =
                                        viewer.imageryLayers.addImageryProvider(
                                            layerOpt
                                        )
                                    // 存储
                                    mapLayer.set(val, [layer])
                                } catch (e) {
                                    console.error(e)
                                }
                            })()
                            break
                        // arcgis影像
                        case '4':
                            await (async () => {
                                try {
                                    const layerOpt =
                                        await Cesium.ArcGisMapServerImageryProvider.fromUrl(
                                            'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
                                        )
                                    const layer =
                                        viewer.imageryLayers.addImageryProvider(
                                            layerOpt
                                        )
                                    // 存储
                                    mapLayer.set(val, [layer])
                                } catch (e) {
                                    console.error(e)
                                }
                            })()
                            break
                        // 金安区蓝黑版
                        case '5':
                            ;(() => {
                                const layer =
                                    viewer.imageryLayers.addImageryProvider(
                                        new Cesium.WebMapTileServiceImageryProvider(
                                            {
                                                // 这里是你的 geoserver服务点击查看图层的 url
                                                url: `http://www.591map.net:41020/geowebcache/service/wmts/rest/JAQLHB/{style}/{TileMatrixSet}/{TileMatrixSet}:{TileMatrix}/{TileRow}/{TileCol}?format=image/png`,
                                                // layer: 'JAQLHB', // 图层名称
                                                // style : 'default',
                                                // format : 'image/png',
                                                tileMatrixSetID:
                                                    'EPSG:3857_JAQLHB', //查询对应的tileMatrixSet参数填入
                                                tilingScheme:
                                                    new Cesium.WebMercatorTilingScheme(), // 3857切片规则
                                                minimumLevel: 0, // 最小级别
                                                maximumLevel: 19, // 最大级别
                                                rectangle:
                                                    Cesium.Rectangle.fromDegrees(
                                                        115.80981817361226,
                                                        31.24621665324839,
                                                        117.7432766391035,
                                                        32.07156734829832
                                                    ), // 地图瓦片矩形范围
                                            }
                                        )
                                    )
                                viewer.flyTo(layer, { duration: 0.0 })
                                // 存储
                                mapLayer.set(val, [layer])
                            })()
                            break
                        // 无图层
                        case '-1':
                            delLayerAll()
                            break
                    }
                } catch (e) {
                    console.error(e)
                    removeMask() // 关闭遮罩
                } finally {
                    removeMask() // 关闭遮罩
                }
            }

            Cesium.knockout
                .getObservable(layerChecked, 'layerValue')
                .subscribe(setLayer)
            // ---------------地形加载---------------------------------------
            const terrainChecked = {
                terrainValue: '-1',
            }
            // 监测属性，KnockoutJS轻量级的UI类库
            Cesium.knockout.track(terrainChecked)
            // 激活属性, 与html控件绑定
            Cesium.knockout.applyBindings(
                terrainChecked,
                document.querySelector('.terrain')
            )

            // 设置地形
            async function setTerrain(val) {
                createMask() // 打开遮罩
                try {
                    switch (val) {
                        // bing地形--需要申请cesium--key
                        case '1':
                            viewer.terrainProvider =
                                await Cesium.createWorldTerrainAsync({
                                    // requestVertexNormals: true // 指示客户端是否应以每个顶点法线的形式向服务器请求其他照明信息（如果可用）的标志。
                                    // requestWaterMask: true,// 指示客户端是否应从服务器请求每个磁贴的水掩码（如果可用）的标志。
                                })
                            break
                        // arcgis地形
                        case '2':
                            const terrainProvider =
                                await Cesium.ArcGISTiledElevationTerrainProvider.fromUrl(
                                    'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer'
                                )
                            viewer.terrainProvider = terrainProvider
                            break
                        // 无地形
                        case '-1':
                            viewer.terrainProvider =
                                new Cesium.EllipsoidTerrainProvider()
                            break
                    }
                } catch (e) {
                    console.error(e)
                    removeMask() // 关闭遮罩
                } finally {
                    removeMask() // 关闭遮罩
                }
            }

            Cesium.knockout
                .getObservable(terrainChecked, 'terrainValue')
                .subscribe(setTerrain)
            // ---------------场景调整---------------------------------------
            const sceneParam = {
                depthTestAgainstTerrain: true, // 深度检测
                wireframeTerrain: false, // 球面三角网
                mapTime: '', // 时间
                brightness: 1.0, // 场景亮度
                floodlightEnabled: false, // 泛光开关
                floodlightGlowOnly: false, // 只保留泛光效果
                floodlightContrast: 120, // 泛光对比度
                floodlightBrightness: -0.43, // 泛光亮度
                floodlightDelta: 1, // 泛光阈值
                floodlightSigma: 2, // 泛光高斯模糊
                floodlightStepSize: 1, // 泛光步长
            }
            // 监测sceneParam中的属性，KnockoutJS轻量级的UI类库
            Cesium.knockout.track(sceneParam)
            // 激活属性, 将sceneParam对象与html控件绑定
            Cesium.knockout.applyBindings(
                sceneParam,
                document.querySelector('.mapScene')
            )

            // viewer.scene.globe._surface.tileProvider._debug.wireframe = enabled; // 三角网
            // viewer.scene.globe.depthTestAgainstTerrain = true; // 高程遮挡效果
            // 获取当前日期
            function getData() {
                const currentDate = new Date()
                const year = currentDate.getFullYear()
                const month = currentDate.getMonth() + 1
                const day = currentDate.getDate()
                return `${year}/${month}/${day}`
            }

            // 小时分钟格式转换为分钟数
            function changeStrToMinutes(str) {
                const arrminutes = str.split(':')
                if (arrminutes.length === 2) {
                    return (
                        parseInt(arrminutes[0]) * 60 + parseInt(arrminutes[1])
                    )
                } else {
                    return 0
                }
            }

            // 分钟转换成小时显示
            function minutesToTime(minutes) {
                let hours = Math.floor(minutes / 60)
                let mins = minutes % 60
                // 格式化为两位数的字符串
                hours = hours < 10 ? '0' + hours : hours
                mins = mins < 10 ? '0' + mins : mins
                return hours + ':' + mins
            }

            // 设置场景时间
            function setMapTime(val) {
                const hours = minutesToTime(val)
                // 设置地图场景时间
                viewer.clock.currentTime = Cesium.JulianDate.fromDate(
                    new Date(`${getData()} ${hours}:00`)
                )
                // 设置dom时间显示
                document.querySelector('.mapScene .mapTimeVal').innerHTML =
                    hours
            }

            // 设置场景亮度
            function setBrightness(val) {
                // 亮度设置
                if (!viewer.scene.brightness) {
                    const stages = viewer.scene.postProcessStages
                    viewer.scene.brightness = stages.add(
                        Cesium.PostProcessStageLibrary.createBrightnessStage()
                    )
                    viewer.scene.brightness.enabled = true
                }
                viewer.scene.brightness.uniforms.brightness = Number(val)
            }

            // 设置场景泛光
            function setBloom() {
                // 地图场景设置
                const bloom = viewer.scene.postProcessStages.bloom
                bloom.enabled = Boolean(sceneParam.floodlightEnabled)
                bloom.uniforms.glowOnly = Boolean(sceneParam.floodlightGlowOnly)
                bloom.uniforms.contrast = Number(sceneParam.floodlightContrast)
                bloom.uniforms.brightness = Number(
                    sceneParam.floodlightBrightness
                )
                bloom.uniforms.delta = Number(sceneParam.floodlightDelta)
                bloom.uniforms.sigma = Number(sceneParam.floodlightSigma)
                bloom.uniforms.stepSize = Number(sceneParam.floodlightStepSize)
            }

            // 监听属性变化
            for (const name in sceneParam) {
                if (sceneParam.hasOwnProperty(name)) {
                    if (name === 'depthTestAgainstTerrain') {
                        // 深度检测--调整
                        Cesium.knockout
                            .getObservable(sceneParam, name)
                            .subscribe(value => {
                                viewer.scene.globe.depthTestAgainstTerrain =
                                    value
                            })
                    } else if (name === 'wireframeTerrain') {
                        // 球面三角网--调整
                        Cesium.knockout
                            .getObservable(sceneParam, name)
                            .subscribe(value => {
                                viewer.scene.globe._surface.tileProvider._debug.wireframe =
                                    value
                            })
                    } else if (name === 'mapTime') {
                        // 场景时间--调整
                        Cesium.knockout
                            .getObservable(sceneParam, name)
                            .subscribe(setMapTime)
                    } else if (name === 'brightness') {
                        // 场景亮度--调整
                        Cesium.knockout
                            .getObservable(sceneParam, name)
                            .subscribe(setBrightness)
                    } else {
                        // 泛光开关--调整
                        Cesium.knockout
                            .getObservable(sceneParam, name)
                            .subscribe(setBloom)
                    }
                }
            }

            // ----------------------------------------------------------------------
            initViewer({ target: 'cesiumContainer' }) // 初始化地图场景
            setTime() // 设置地图场景时间为北京时间
            setMapTime(changeStrToMinutes('12:00')) // 设置地图场景时间,为当天日期的中午12:00（太阳光照正中午，位于头顶）
            layerChecked.layerValue = '1' // 添加-底图
            // terrainChecked.terrainValue = '1';// 添加-地形
        </script>
    </body>
</html>
